package com.littlefluffytoys.littlefluffylocationlibrary;

import java.io.Serializable;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.format.DateFormat;
import rest.o.gram.location.Location;

public class LocationInfo implements Serializable, Location {

    private static final long serialVersionUID = 1L;

    public long lastLocationUpdateTimestamp;
    public long lastLocationBroadcastTimestamp;
    public float lastLat;
    public float lastLong;
    public int lastAccuracy;
    public String originProvider;

    /**
     * The constructor populates the public fields with the latest location info.
     */
    public LocationInfo(final Context context) {
        refresh(context);
    }

    /**
     * Call this method to retrieve the latest location info.
     */
    public void refresh(final Context context) {
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        lastLocationUpdateTimestamp = prefs.getLong(LocationLibraryConstants.SP_KEY_LAST_LOCATION_UPDATE_TIME, 0);
        lastLocationBroadcastTimestamp = prefs.getLong(LocationLibraryConstants.SP_KEY_LAST_LOCATION_BROADCAST_TIME, 0);
        lastLat = ((int) (prefs.getFloat(LocationLibraryConstants.SP_KEY_LAST_LOCATION_UPDATE_LAT, Integer.MIN_VALUE) * 1000000f)) / 1000000f;
        lastLong = ((int) (prefs.getFloat(LocationLibraryConstants.SP_KEY_LAST_LOCATION_UPDATE_LNG, Integer.MIN_VALUE) * 1000000f)) / 1000000f;
        lastAccuracy = prefs.getInt(LocationLibraryConstants.SP_KEY_LAST_LOCATION_UPDATE_ACCURACY, Integer.MAX_VALUE);
        originProvider = prefs.getString(LocationLibraryConstants.SP_KEY_LAST_LOCATION_UPDATE_ORIGIN_PROVIDER, null);
    }

    /**
     * @return Gets last update time stamp
     */
    @Override
    public long getLastUpdateTimestamp() {
        return lastLocationUpdateTimestamp;
    }

    /**
     * @return Gets last broadcast time stamp
     */
    @Override
    public long getLastBroadcastTimestamp() {
        return lastLocationBroadcastTimestamp;
    }

    /**
     * @return Gets last latitude
     */
    @Override
    public float getLastLat() {
        return lastLat;
    }

    /**
     * @return Gets last longitude
     */
    @Override
    public float getLastLong() {
        return lastLong;
    }

    /**
     * @return Gets last accuracy
     */
    @Override
    public int getLastAccuracy() {
        return lastAccuracy;
    }

    /**
     * @return Gets last origin provider
     */
    @Override
    public String getLastOriginProvider() {
        return originProvider;
    }

    /**
     * @return true if any location data has been received since the phone last powered up.
     */
    @Override
    public boolean anyLocationDataReceived() {
        return (lastLocationUpdateTimestamp != 0);
    }

    /**
     * @return true if any location data has been broadcast since the phone last powered up.
     */
    @Override
    public boolean anyLocationDataBroadcast() {
        return (lastLocationBroadcastTimestamp != 0);
    }

    /**
     * @return true if the latest location has been broadcast by the periodic broadcaster,
     *         false if a periodic broadcast is pending.
     */
    @Override
    public boolean hasLatestDataBeenBroadcast() {
        return (anyLocationDataBroadcast() && (lastLocationUpdateTimestamp == lastLocationBroadcastTimestamp));
    }

    /**
     * @return timestamp age in seconds
     */
    @Override
    public long getTimestampAgeInSeconds() {
        return (Math.max((System.currentTimeMillis() - lastLocationUpdateTimestamp) / 1000, 0L));
    }

    /**
     * @return time and day as "hh:mm, ddd" or "hh:mm:ss, ddd"
     */
    public static String formatTimeAndDay(final long timestamp, final boolean includeSeconds) {
        return (DateFormat.format("kk:mm" + (includeSeconds ? ".ss" : "") + ", E", timestamp).toString());
    }

    @Override
    public String toString() {
        return (String.format("lastLocationUpdateTimestamp=%1$s lastLocationBroadcastTimestamp=%2$s lastLat=%3$.6f lastLong=%4$.6f lastAccuracy=%5$d",
                lastLocationUpdateTimestamp != 0 ? formatTimeAndDay(lastLocationUpdateTimestamp, true) : "none",
                lastLocationBroadcastTimestamp != 0 ? formatTimeAndDay(lastLocationBroadcastTimestamp, true) : "none",
                lastLat, lastLong, lastAccuracy));
    }
}

